package com.sishu.njrtsdms.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.sishu.njrtsdms.domain.core.GenericServiceImpl;
import com.sishu.njrtsdms.domain.dto.DictDataForTreeDTO;
import com.sishu.njrtsdms.domain.dto.DictDataNormalDTO;
import com.sishu.njrtsdms.domain.dto.DictTypeForTreeDTO;
import com.sishu.njrtsdms.domain.dto.DictTypeNormalDTO;
import com.sishu.njrtsdms.domain.vo.DictDataVO;
import com.sishu.njrtsdms.domain.vo.DictTypeVO;
import com.sishu.njrtsdms.jooq.codegen.tables.daos.DictDataDAO;
import com.sishu.njrtsdms.jooq.codegen.tables.daos.DictTypeDAO;
import com.sishu.njrtsdms.jooq.codegen.tables.pojos.DictData;
import com.sishu.njrtsdms.service.DictDataService;
import org.jooq.types.ULong;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DictDataServiceImpl extends GenericServiceImpl<DictData, ULong>
        implements DictDataService {

    @Autowired
    private DictTypeDAO dictTypeDAO;
    private final DictDataDAO dictDataDAO;

    public DictDataServiceImpl(DictDataDAO dao) {
        super(dao);
        dictDataDAO = dao;
    }

    @Override
    public List<DictTypeVO> listDictType(DictTypeNormalDTO dictTypeNormalDTO) {
        return dictTypeDAO.fetchByConditions(dictTypeNormalDTO);
    }

    @Override
    public List<DictDataVO> listDictData(DictDataNormalDTO dictDataNormalDTO) {
        return dictDataDAO.fetchByConditions(dictDataNormalDTO);
    }

    @Override
    public List<Tree<ULong>> listDictDataForTree(DictDataForTreeDTO dictDataForTreeDTO) {
        var dictDataVOList = dictDataDAO.fetchByConditions(dictDataForTreeDTO);
        if (CollUtil.isEmpty(dictDataVOList)) return null;

        // 找寻当前顶层的parentId
        ULong rootId;
        // 确定深度,最多4层
        int deep;
        var topDictTypeId = dictDataForTreeDTO.topDictTypeId();
        if (topDictTypeId == null) {
            rootId = ULong.valueOf(0);
            deep = 4;
        } else {
            var dictDataVO = dictDataVOList.stream()
                    .filter(it -> it.dictType().dictTypeId()
                            .equals(topDictTypeId))
                    .findAny()
                    .orElse(null);
            if (dictDataVO == null) return null;
            rootId = dictDataVO.parentId();
            String ancestorsArrayStr = dictDataVO.ancestors();
            var ancestorsLength = StrUtil.replace(
                    (
                            StrUtil.replace(
                                    ancestorsArrayStr,
                                    StrUtil.BRACKET_START,
                                    StrUtil.EMPTY)
                    ),
                    StrUtil.BRACKET_END,
                    StrUtil.EMPTY
            ).split(StrUtil.COMMA).length;
            deep = 5 - ancestorsLength;
        }

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setNameKey("dictDataLabel");
        treeNodeConfig.setWeightKey("sort");
        treeNodeConfig.setIdKey("dictDataId");
        treeNodeConfig.setChildrenKey("children");
        treeNodeConfig.setDeep(deep);

        return TreeUtil.build(dictDataVOList, rootId, treeNodeConfig,
                (DictDataVO dictDataVO, Tree<ULong> tree) -> {
                    tree.setId(dictDataVO.dictDataId());
                    tree.putExtra("ancestors", dictDataVO.ancestors());
                    tree.setParentId(dictDataVO.parentId());
                    tree.setWeight(dictDataVO.sort());
                    tree.setName(dictDataVO.dictDataLabel());
                    tree.putExtra("dictDataValue", dictDataVO.dictDataValue());
                    tree.putExtra("desc", dictDataVO.desc());
                    tree.putExtra("dictType", dictDataVO.dictType());
                });
    }

    @Override
    public List<Tree<ULong>> listDictTypeForTree(DictTypeForTreeDTO dictDataForTreeDTO) {
        var dictTypeVOList = dictTypeDAO.fetchByConditions(dictDataForTreeDTO);
        if (CollUtil.isEmpty(dictTypeVOList)) return null;

        // 找寻当前顶层的parentId
        ULong rootId;
        // 深度
        int deep;
        var topDictTypeCode = dictDataForTreeDTO.topDictTypeCode();
        if (StrUtil.isBlank(topDictTypeCode)) {
            rootId = ULong.valueOf(0);
            deep = 4;
        } else {
            var dictTypeVO = dictTypeVOList.stream()
                    .filter(it -> it.dictTypeCode()
                            .equals(topDictTypeCode))
                    .findAny()
                    .orElse(null);
            if (dictTypeVO == null) return null;
            rootId = dictTypeVO.parentId();
            String ancestorsArrayStr = dictTypeVO.ancestors();
            var ancestorsLength = StrUtil.replace(
                    (
                            StrUtil.replace(
                                    ancestorsArrayStr,
                                    StrUtil.BRACKET_START,
                                    StrUtil.EMPTY)
                    ),
                    StrUtil.BRACKET_END,
                    StrUtil.EMPTY
            ).split(StrUtil.COMMA).length;
            deep = 5 - ancestorsLength;
        }

        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        treeNodeConfig.setNameKey("dictTypeName");
        treeNodeConfig.setIdKey("dictTypeId");
        treeNodeConfig.setChildrenKey("children");
        treeNodeConfig.setDeep(deep);

        return TreeUtil.build(dictTypeVOList, rootId, treeNodeConfig,
                (DictTypeVO dictTypeVO, Tree<ULong> tree) -> {
                    tree.setId(dictTypeVO.dictTypeId());
                    tree.setParentId(dictTypeVO.parentId());
                    tree.putExtra("ancestors", dictTypeVO.ancestors());
                    tree.setName(dictTypeVO.dictTypeName());
                    tree.putExtra("dictTypeCode", dictTypeVO.dictTypeCode());
                    if (tree.getChildren() == null) {
                        tree.setChildren(null);
                    }
                });
    }
}